#!/bin/bash
#
# Server for the Blog application in CGI!
#
# Updates will have to be done locally (no web editing), but the wiki will
# make up for it. 
#
#    Copyright 2015 K. Zimmermann - https://notabug.org/kzimmermann
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

#-- Built-in variables: --#

# if you wish to use markdown, download the script and reference it in
# the variable below. Otherwise only plain paragraphs are supported.
# Remember to reference the *full* path to the script!
markdown="./Markdown.pl"

# change this to a name that no one could guess (leave the .db extension).
db="main.db"

date=""

#-- /Variables --#

#-- Predefined functions: --#

# Fetcher of content from the database:

fetcher() {
    # Pass $1 as the element you want and $2 the id of the blog entry!
    echo -e "$(sqlite3 $db "SELECT $1 FROM articles WHERE id=$2")"
}

create_paragraphs() {
    # Pass $1 as the full text to be parsed.
    final="
<p>
"
    final="$final"$(echo "$1" | sed 's/^$/\<\/p\>\n\<p\>/g' )
    final=$final"
</p>"
    echo "$final"
}

# Markdown formatting

parse_markdown() {
    # pass content to be parsed as $1
    if [[ -n "$markdown" ]]
    then
        echo "$1" | $markdown
    else
        # fall back to plain paragraphs:
        create_paragraphs "$1"
    fi
}

#-- Query string parsing session --#

# Assume a query of http://site.com/?article&id=X
# If we're searching, this query will come up: (...)/?search=TOKEN

page=$(echo "$QUERY_STRING" | cut -d "&" -f 1 | cut -d "=" -f 1)
id=$(echo "$QUERY_STRING" | cut -d "&" -f 2 | cut -d "=" -f 2)

#-- Page selection routines --#
#
# To add a new permanent page, simply add a new entry like this before 
# the * ) line:
# 
#     "page_url" ) 
#     title="Page title goes here"
#     content="$($markdown content_of_page.md)"
#     ;;
#
# You will need an external page file for this, preferably in Markdown.
#

case "$page" in
    "" ) 
    title="Home"
    content="$($markdown home.md)"
    ;;
    "articles")
    title="Article database"
    content="
    <p>
        Articles curated by my mind in its full inspiration. May be hard to 
        come by depending on the week, but I'll try my best to put something
        in at least every week to say what's going on my mind.
    </p>
    <form action=\"/\" method=\"GET\">
        <input type=\"text\" name=\"search\" placeholder=\"Search for an article\" />
        <input type=\"submit\" value=\"Search\" /> <br />
    </form>
    <p>
        You may also want to grab my <a href=\"feed.rss\">RSS feed</a> just in
        case if there are delays in the updates and stuff. I'm still working
        on it, though.
    </p>
    <ul>
    "
    articles_links=$(sqlite3 $db "SELECT id FROM articles ORDER BY pubdate DESC")
    for article in $articles_links
    do
        article_title=$(sqlite3 $db "SELECT title FROM articles WHERE id=$article")
        article_pubdate=$(sqlite3 $db "SELECT pubdate FROM articles WHERE id=$article")
        content=$content"<li><a href=\"?article\&id=$article\">$article_title</a> - $article_pubdate</li>
"
    done
    content=$content"</ul>
    "
    ;;
    "article")
    title=$(fetcher "title" $id)
    # Sanity check if article does not exist:
    if [ -z "$title" ]
    then
        title="Article not found"
        content="<p>This article does not exist.</p>
        <p>You may want to try the <a href=\"?articles\">full article list</a>.</p>
        "
    else
        content=$(fetcher "body" $id)
        content=$(parse_markdown "$content")
        date="<p>Last updated on "$(fetcher "pubdate" $id)"</p>"

        # Increment page views by +1
        sqlite3 $db "
            UPDATE articles SET pageviews = 
                (SELECT pageviews + 1 FROM articles WHERE id = $id) 
            WHERE id = $id;
        "
    fi
    ;;
    "search" ) 
    title="Search results for $id"
    results="$(
        sqlite3 $db "SELECT id FROM articles WHERE title LIKE '%$id%' OR body LIKE '%$id%'" 
    )"
    if [[ -z "$results" ]]
    then
        content="
        <p>
            Sorry, no results found for '$id'.
        </p>
        "
    else
        content="
        <p>
            Articles matching '$id':
        </p>
        <ul>
        "
        for match in $results
        do
            content=$content"<li><a href=\"?article\&id=$match\">
            $(sqlite3 $db "SELECT title FROM articles WHERE id=$match")
            </a></li>
            "
        done
    fi
    content=$content"</ul>
        <form action=\"/\" method=\"GET\">
            <input type=\"text\" name=\"search\" placeholder=\"Search for an article\" />
            <input type=\"submit\" value=\"Search\" /> <br />
        </form>
        "
    ;;
    "contact")
    title="Contact me"
    content="$($markdown contact.md)"
    ;;
    "privacypolicy" )
    title="Privacy policy"
    content="$($markdown privacypolicy.md)"
    ;;
    * )
    title="Page not Found"
    content="<p>
        The page you were looking for has not been found.
    </p>
    <p>
        You might want to check out the <a href=\"/wiki\">Wiki</a> or go to the home page.
    </p>
    <p>You searched for: $page</p>
    "
    ;;
esac

#-- Serve the content! --#

printf "Content-Type: text/html\nCharset: UTF-8\n\n"

content="$(echo "$content" | tr -d '\n')"

# It's hard to find the perfect character to use in sed. It has to be 1-byte
# long, and not used in common speech. ^ is not perfect, but works well so
# far.

cat template.html | sed "s^{{title}}^$title^g" |
    sed "s^{{content}}^$content^g" |
    sed "s^{{date}}^$date^g"
